package com.hyt.it.ogt.kq.service.bm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Maps;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseEntity;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.cj.enums.ComponentNameEnum;
import com.hyt.it.ogt.cj.model.entity.ProjectCollectInfo;
import com.hyt.it.ogt.cj.model.entity.ProjectCollectInfoOption;
import com.hyt.it.ogt.cj.model.vo.OptionTree;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoOptionService;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoService;
import com.hyt.it.ogt.cj.utils.StringUtils;
import com.hyt.it.ogt.kq.common.bm.utils.DateUtil;
import com.hyt.it.ogt.kq.common.config.exception.InvalidRequestException;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentInfoMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.UserPermissionMapper;
import com.hyt.it.ogt.kq.service.bm.model.entity.UserPermission;
import com.hyt.it.ogt.kq.service.bm.model.vo.*;
import com.hyt.it.ogt.kq.service.bm.service.IUserPermissionService;
import com.hyt.loginfo.model.UserVO;
import com.hyt.loginfo.model.param.QueryUsersParam;
import com.hyt.loginfo.remote.PermissionLoginClient;
import com.hyt.loginfo.service.IBaseLoginService;
import com.hyt.loginfo.util.UserIdToNameUtil;
import com.hyt.model.PageParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liteng
 * @since 2021-03-01
 */
@Slf4j
@Service
public class UserPermissionServiceImpl extends BaseServiceImpl<UserPermissionMapper, UserPermission> implements IUserPermissionService {

    @Autowired
    private IProjectCollectInfoService iProjectCollectInfoService;

    @Autowired
    private IProjectCollectInfoOptionService iProjectCollectInfoOptionService;

    @Resource
    UserPermissionMapper userPermissionMapper;

    @Resource
    StudentInfoMapper studentInfoMapper;

    @Autowired
    IBaseLoginService iBaseLoginService;
    @Resource
    PermissionLoginClient uaClient;
    @Resource
    UserIdToNameUtil<UserPermissionInfo> userIdToNameUtil;


    @Transactional(rollbackFor = Exception.class)
    public void saveUserPermission(UserPermissionVo vo) throws Exception {
        QueryWrapper<ProjectCollectInfo> infoWrapper = new QueryWrapper<ProjectCollectInfo>();
        infoWrapper.eq("component_name", "area");
        infoWrapper.eq("project_id", vo.getProjectId());
        infoWrapper.eq("is_del_flag", Boolean.FALSE);
        ProjectCollectInfo projectCollectInfo = Optional.ofNullable(iProjectCollectInfoService.getOne(infoWrapper))
                .orElseThrow(() -> new InvalidRequestException(31141102));

        QueryWrapper<ProjectCollectInfoOption> optionWrapper = new QueryWrapper<ProjectCollectInfoOption>();
        optionWrapper.eq("project_collect_info_id", projectCollectInfo.getId());
        List<ProjectCollectInfoOption> optionList = iProjectCollectInfoOptionService.list(optionWrapper);

        for (int i = 0; i < vo.getUserList().size(); i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("project_id", vo.getProjectId());
            map.put("user_id", vo.getUserList().get(i));
            this.removeByMap(map);

            UserPermission userPermission = new UserPermission();
            for (int j = 0; j < vo.getOptionList().size(); j++) {
                userPermission.setId(UUIDUtils.newSortUUID());
                userPermission.setProjectId(vo.getProjectId());
                userPermission.setUserId(vo.getUserList().get(i));
                for (int n = 0; n < optionList.size(); n++) {
                    if (optionList.get(n).getOptionValue().equals(vo.getOptionList().get(j))) {
                        userPermission.setCjProjectCollectInfoOptionId(optionList.get(n).getId());
                        break;
                    }
                }
                this.save(userPermission);
            }
        }
    }


    public List<UserPermissionVo> queryUserPermission(String projectId) throws Exception {
        List<UserPermissionVo> volist = new ArrayList<UserPermissionVo>();
        try {
            QueryWrapper<UserPermission> wapper = new QueryWrapper<UserPermission>();
            wapper.eq("project_id", projectId);
            List<UserPermission> list = this.list(wapper);
            Set<String> userSet = new LinkedHashSet<String>();
            Set<String> optionSet = new LinkedHashSet<String>();
            List<String> userList = new ArrayList<String>();
            List<String> optionList = new ArrayList<String>();
            //执行去重操作
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    userSet.add(list.get(i).getUserId());
                    optionSet.add(list.get(i).getCjProjectCollectInfoOptionId());
                }
            }
            for (String userId : userSet) {
                userList.add(userId);
            }
            for (String optionId : optionSet) {
                optionList.add(optionId);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            throw ex;
        }
        return volist;
    }

    public List<String> queryPermissionByUserId(String projectId, String userId) {
        List<String> resultList = new ArrayList<String>();
        List<UserPermissionInfo> list = userPermissionMapper.queryUserPermissionVo(projectId, userId);
        // 查询是否有区域权限
        QueryWrapper<ProjectCollectInfo> infoWrapper = new QueryWrapper<ProjectCollectInfo>();
        infoWrapper.eq("component_name", "area");
        infoWrapper.eq("project_id", projectId);
        infoWrapper.eq("is_del_flag", 0);
        ProjectCollectInfo projectCollectInfo = iProjectCollectInfoService.getOne(infoWrapper);
        if (projectCollectInfo != null) {
            QueryWrapper<ProjectCollectInfoOption> optionWrapper = new QueryWrapper<ProjectCollectInfoOption>();
            optionWrapper.eq("project_collect_info_id", projectCollectInfo.getId());
            List<ProjectCollectInfoOption> optionList = iProjectCollectInfoOptionService.list(optionWrapper);
            Set<String> resultSet = new HashSet<String>();
            if (list != null && list.size() > 0) {
                List<String> strList = new ArrayList<String>();
                for (int i = 0; i < list.size(); i++) {
                    strList.add(list.get(i).getOptionValue());
                }
                resultSet = buildTree(resultSet, strList, optionList);
                if (resultSet != null && resultSet.size() > 0) {
                    for (String key : resultSet) {
                        resultList.add(key);
                    }
                }
            }
            return resultList;
        } else {
            return null;
        }
    }

    public List<OptionTree> loadPermissionByUserId(String projectId) {
        QueryWrapper<ProjectCollectInfo> infoWrapper = new QueryWrapper<ProjectCollectInfo>();
        infoWrapper.eq("component_name", "area");
        infoWrapper.eq("project_id", projectId);
        infoWrapper.eq("is_del_flag", Boolean.FALSE);
        ProjectCollectInfo projectCollectInfo = iProjectCollectInfoService.getOne(infoWrapper);
        if (ObjectUtil.isEmpty(projectCollectInfo)) {
            return null;
        }

        QueryWrapper<ProjectCollectInfoOption> optionWrapper = new QueryWrapper<ProjectCollectInfoOption>();
        optionWrapper.eq("project_collect_info_id", projectCollectInfo.getId());
        List<OptionTree> optionTreeList = iProjectCollectInfoOptionService.list(optionWrapper)
                .stream()
                .parallel()
                .map(option -> {
                    OptionTree optionTree = new OptionTree();
                    optionTree.setParentValue(option.getParentOptionValue());
                    optionTree.setValue(option.getOptionValue());
                    optionTree.setLabel(option.getOptionLabel());
                    return optionTree;
                }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(optionTreeList)) {
            optionTreeList = bulidByLoop(optionTreeList);
        }
        return optionTreeList;
    }

    public Set<String> buildTree(Set<String> resultSet, List<String> list, List<ProjectCollectInfoOption> optionList) {
        for (int j = 0; j < list.size(); j++) {
            List<String> temp = new ArrayList<String>();
            boolean flag = true;
            for (int i = 0; i < optionList.size(); i++) {
                if (optionList.get(i).getParentOptionValue().equals(list.get(j))) {
                    temp.add(optionList.get(i).getId());
                    resultSet.add(optionList.get(i).getId());
                }
            }
            resultSet.add(list.get(j));
            buildTree(resultSet, temp, optionList);
        }
        return resultSet;
    }

    public IPage<UserPermissionInfo> queryPermissionPage(PageParam<UserPermissionInfo> pageParam, String projectId, List<String> userIds, List<String> areaCodes) {
        // 获取当前报名项目中所有的用户ID
        if (CollUtil.isEmpty(userIds)) {
            userIds = listProjectUserId(projectId);
        }
        //查出id和name对应的map
        QueryUsersParam queryUsersParam = QueryUsersParam.builder()
                .userids(userIds)
                .build();
        Map<String, UserVO> stringUserVOMap = Optional.ofNullable(uaClient.getUsersByIds(queryUsersParam))
                .map(ApiResponse::getData)
                .map(Collection::stream)
                .map(data -> data
                        .filter(vo -> StrUtil.isNotBlank(vo.getUserid()))
                        .collect(Collectors.toMap(UserVO::getUserid, vo -> vo)))
                .orElseGet(Maps::newHashMap);
        // 获取返回的用户ID
        Set<String> permissionUserIds = stringUserVOMap.keySet();
        if (CollUtil.isEmpty(permissionUserIds)) {
            return null;
        }

        IPage<UserPermissionInfo> page = userPermissionMapper.queryPermissionPage(pageParam, projectId, permissionUserIds, areaCodes);
        page.getRecords()
                .forEach(userPermissionInfo -> Optional.ofNullable(stringUserVOMap.get(userPermissionInfo.getUserId()))
                        .ifPresent(userInfoVO -> {
                            userPermissionInfo.setUserName(userInfoVO.getUsername());
                            userPermissionInfo.setUserPhone(userInfoVO.getPhone());
                        }));
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteUserPermission(String projectId, String userId) {
        userPermissionMapper.deleteUserPermission(projectId, userId.split(","));
    }


    /**
     * 双层循环实现建树,对传入的树节点列表无排序要求
     *
     * @param treeNodes 传入的树节点列表
     * @return
     */
    public List<OptionTree> bulidByLoop(List<OptionTree> treeNodes) {

        List<OptionTree> trees = new ArrayList<OptionTree>();
        for (OptionTree treeNode : treeNodes) {
            /*
             * 根节点的父Id为0,且不要求仅有唯一的根
             */
            if (StringUtils.isBlank(treeNode.getParentValue())) {
                trees.add(treeNode);
            } else {
                boolean flag = false;
                for (int j = 0; j < treeNodes.size(); j++) {
                    if (treeNode.getParentValue().equals(treeNodes.get(j).getValue())) {
                        flag = true;
                    }
                }
                if (!flag) {
                    trees.add(treeNode);
                }
            }
            for (OptionTree it : treeNodes) {
                if (it.getParentValue().equals(treeNode.getValue())) {
                    if (treeNode.getChildren() == null) {
                        treeNode.setChildren(new ArrayList<OptionTree>());
                    }
                    treeNode.getChildren().add(it);
                }
            }
        }
        return trees;
    }

    @Transactional(rollbackFor = Exception.class)
    public void copyUserPermission(String oldProjectId, String newProjectId) {
        QueryWrapper<UserPermission> infoWrapper = new QueryWrapper<UserPermission>();
        infoWrapper.eq("project_id", oldProjectId);
        List<UserPermission> list = this.list(infoWrapper);

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("project_id", newProjectId);
        this.removeByMap(map);

        List<UserPermission> resultList = new ArrayList<UserPermission>();
        if (CollUtil.isNotEmpty(list)) {
            //取出所有的id，并去重
            List<String> ids = list.stream()
                    .map(UserPermission::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            //查出id和name对应的map
            QueryUsersParam queryUsersParam = QueryUsersParam.builder()
                    .userids(ids)
                    .build();
            Map<String, UserVO> stringUserVOMap = Optional.ofNullable(uaClient.getUsersByIds(queryUsersParam))
                    .map(ApiResponse::getData)
                    .map(Collection::stream)
                    .map(data -> data
                            .filter(vo -> com.hyt.core.util.StringUtils.isNotEmpty(vo.getUserid()))
                            .collect(Collectors.toMap(UserVO::getUserid, vo -> vo)))
                    .orElseGet(Maps::newHashMap);
            for (UserPermission userPermission : list) {
                UserVO userVO = stringUserVOMap.get(userPermission.getUserId());
                if (ObjectUtil.isNotEmpty(userVO)) {
                    userPermission.setId(null);
                    userPermission.setProjectId(newProjectId);
                    resultList.add(userPermission);
                }
            }
        }
        this.saveBatch(resultList);
    }

    public Map<String, List<String>> getProjectPermission(String userId) {
        List<UserPermissionInfo> list = userPermissionMapper.queryUserPermissionVo(null, userId);
        return assembleProjectPermission(list);
    }

    @Override
    public Map<String, List<String>> getProjectPermission(String userId, List<String> projectIds) {
        List<UserPermissionInfo> list = userPermissionMapper.queryUserPermissionByProject(userId, projectIds);
        return assembleProjectPermission(list);
    }

    /**
     * 装配报名权限
     *
     * @param list
     * @return
     */
    private Map<String, List<String>> assembleProjectPermission(List<UserPermissionInfo> list) {
        Map<String, List<String>> map = new HashMap<>();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                if (map.get(list.get(i).getProjectId()) != null && map.get(list.get(i).getProjectId()).size() > 0) {
                    map.get(list.get(i).getProjectId()).add(list.get(i).getOptionValue());
                    map.put(list.get(i).getProjectId(), map.get(list.get(i).getProjectId()));
                } else {
                    List<String> permissionList = new ArrayList<String>();
                    permissionList.add(list.get(i).getOptionValue());
                    map.put(list.get(i).getProjectId(), permissionList);
                }
            }
            return map;
        }
        return Maps.newHashMap();
    }

    public int statStudent(String userId, Set<String> deptIds, String startTime, String endTime) {
        String deptId = iBaseLoginService.getDeptId();
        Map<String, List<String>> map = this.getProjectPermission(userId);
        List<UserPermissionStatVo> list = studentInfoMapper.statProjectStudent(deptIds, startTime, endTime);
        List<UserPermissionStatVo> projectList = studentInfoMapper.statOfficeProjectStudent(deptIds, startTime, endTime);
        Map<String, Integer> resultMap = new HashMap<String, Integer>();
        int count = 0;
        if (map != null) {
            if (list != null && list.size() > 0) {

                for (Map.Entry<String, List<String>> me : map.entrySet()) {
                    List<String> permissionList = me.getValue();
                    String projectId = me.getKey();

                    for (String collectId : permissionList) {
                        for (UserPermissionStatVo vo : list) {
                            if (vo.getProjectId().equals(projectId) && vo.getProjectCollectInfoId().equals(collectId)) {
                                count += vo.getStudentNum();
                                break;
                            }
                        }
                    }

                }
            }
        }

        if (projectList != null && projectList.size() > 0) {
            for (UserPermissionStatVo vo : projectList) {
                count += vo.getStudentNum();
            }
        }
        return count;
    }

    public List<StudentStatVo> statStudentByHour(ProjectParam param) {
        String deptId = iBaseLoginService.getDeptId();
        param.setDeptId(deptId);
        Map<String, List<String>> map = this.getProjectPermission(param.getUserId());
        List<UserPermissionStatVo> list = userPermissionMapper.statTimeStudent(param.getOfficeId(), param.getStartTime(), param.getEndTime());
        List<UserPermissionStatVo> projectList = userPermissionMapper.statTimeOfficeStudent(param.getOfficeId(), param.getStartTime(), param.getEndTime(), param.getDeptId());
        Map<String, Integer> resultMap = new HashMap<String, Integer>();
        List<StudentStatVo> resultList = new ArrayList<StudentStatVo>();
        for (int i = 0; i <= 23; i++) {
            String hour = i + "";
            if (i < 10) {
                hour = "0" + hour;
            }
            StudentStatVo studentStatVo = new StudentStatVo();
            studentStatVo.setTime(hour);
            int num = 0;
            if (map != null) {
                if (list != null && list.size() > 0) {
                    for (int j = 0; j < list.size(); j++) {
                        for (Map.Entry<String, List<String>> me : map.entrySet()) {
                            List<String> permissionList = me.getValue();
                            String projectId = me.getKey();
                            for (String collectId : permissionList) {
                                for (UserPermissionStatVo vo : list) {
                                    if (hour.equals(vo.getTime()) && vo.getProjectId().equals(projectId) && vo.getProjectCollectInfoId().equals(collectId)) {
                                        num += vo.getStudentNum();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (projectList != null && projectList.size() > 0) {
                for (UserPermissionStatVo vo : projectList) {
                    if (hour.equals(vo.getTime())) {
                        num += vo.getStudentNum();
                    }
                }
            }
            studentStatVo.setStudentNum(num);
            resultList.add(studentStatVo);
        }
        return resultList;
    }

    public List<StudentStatVo> statStudentByDate(ProjectParam param) {
        Map<String, List<String>> map = this.getProjectPermission(param.getUserId());
        String deptId = iBaseLoginService.getDeptId();
        param.setDeptId(deptId);
        List<String> daylist = new ArrayList<String>();
        List<UserPermissionStatVo> list = userPermissionMapper.statDateStudent(param.getOfficeId(), param.getStartTime(), param.getEndTime());
        List<UserPermissionStatVo> projectList = userPermissionMapper.statDateOfficeStudent(param.getOfficeId(), param.getStartTime(), param.getEndTime(), param.getDeptId());
        Map<String, Integer> resultMap = new HashMap<String, Integer>();
        List<StudentStatVo> resultList = new ArrayList<StudentStatVo>();
        if ("2".equals(param.getState())) {
            daylist = DateUtil.getDayListOfMonth();
        } else {
            daylist = DateUtil.getWeekDateList();
        }
        for (int i = 0; i < daylist.size(); i++) {
            String time = daylist.get(i);
            StudentStatVo studentStatVo = new StudentStatVo();
            studentStatVo.setTime(time);
            int num = 0;
            if (map != null) {
                if (list != null && list.size() > 0) {
                    for (int j = 0; j < list.size(); j++) {
                        for (Map.Entry<String, List<String>> me : map.entrySet()) {
                            List<String> permissionList = me.getValue();
                            String projectId = me.getKey();
                            for (String collectId : permissionList) {
                                for (UserPermissionStatVo vo : list) {
                                    if (time.equals(vo.getTime()) && vo.getProjectId().equals(projectId) && vo.getProjectCollectInfoId().equals(collectId)) {
                                        num += vo.getStudentNum();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (projectList != null && projectList.size() > 0) {
                for (UserPermissionStatVo vo : projectList) {
                    if (time.equals(vo.getTime())) {
                        num += vo.getStudentNum();
                    }
                }
            }
            studentStatVo.setStudentNum(num);
            resultList.add(studentStatVo);
        }
        return resultList;
    }

    @Override
    public List<String> listProjectUserId(String projectId) {
        return this.lambdaQuery()
                .select(UserPermission::getUserId)
                .eq(BaseEntity::getDelFlag, Boolean.FALSE)
                .eq(UserPermission::getProjectId, projectId)
                .list()
                .stream()
                .map(UserPermission::getUserId)
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());

    }

    /***
     * 查询项目是不是需要校验区域权限
     */
    public boolean needCheckAreaPermission(String projectId) {
        QueryWrapper<ProjectCollectInfo> infoWrapper = new QueryWrapper<ProjectCollectInfo>();
        infoWrapper.eq("component_name", "area");
        infoWrapper.eq("project_id", projectId);
        infoWrapper.eq("is_del_flag", 0);
        List<ProjectCollectInfo> areaCollectInfo = iProjectCollectInfoService.list(infoWrapper);
        return CollUtil.isNotEmpty(areaCollectInfo);
    }

    /***
     *  查询项目是否有机构采集字段
     */
    public boolean needCheckOfficePermission(String projectId) {
        QueryWrapper<ProjectCollectInfo> infoWrapper = new QueryWrapper<ProjectCollectInfo>();
        infoWrapper.eq("component_name", ComponentNameEnum.office.getCode());
        infoWrapper.eq("project_id", projectId);
        infoWrapper.eq("is_del_flag", 0);
        List<ProjectCollectInfo> officeCollectInfo = iProjectCollectInfoService.list(infoWrapper);
        return CollUtil.isNotEmpty(officeCollectInfo);
    }
}
